group_by和summrise连用后,分组计算就很方便。
关于分组计算这个话题,我在写过的那些帖子里面,经常用到的就是group_by
联合summarise
比如多探针求最大值,多甲基化位点求平均值,TCGA中miRNA求最大值
GEO芯片中多个探针对应一个基因,是求平均值还是保留最大值?
批量读入TCGA的miRNA数据(注意细节)
R语言学习路上的忆苦思甜
凡是重复的,全部删掉,一个都不留!
从零开始学技能,以数据集合upset图为例。
group_by
按照某一列把数据框分成多个组我是知道的,但是summarise
我就比较疑惑了,因为他们家还有sammarise_all
, 而且哪些函数能用在 summarise
中,我也没有总结过,这次就准备来解决这个事情。
先来创建一个数据框来作练习。
set.seed(1119)
data <- data.frame(ID=rep(LETTERS,each=3),
sample1=sample(seq(10,1000),78),
sample2=sample(seq(10,100),78),
sample3=sample(seq(20,500),78))
其中set.seed(1119)
是设定了一个随机种子,要保证大家跟我的结果一致
group_by
和summarise
都存在于dplyr
这个包中,所以需要先加载R包。
library(dplyr)
然后我们来看一个最简单的运用,summarise
中直接给n()
来统计分组变量的频次
data %>%
group_by(ID) %>%
summarise(n())
# A tibble: 26 x 2
ID `n()`
<fct> <int>
1 A 3
2 B 3
3 C 3
4 D 3
5 E 3
6 F 3
7 G 3
8 H 3
9 I 3
10 J 3
最终得到两列,统计了ID这一列数据出现的频次。这个功能跟我们的明星函数table
一样
table(data$ID)
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
在本次的sammarise
中,我们用的是summarise(n())
这种形式,所以结果中,第二列的列名是n()
,我们可以通过赋值来改变列的名字,比如这样
data %>%
group_by(ID) %>%
summarise(n=n())
# A tibble: 26 x 2
ID n
<fct> <int>
1 A 3
2 B 3
3 C 3
4 D 3
5 E 3
6 F 3
7 G 3
8 H 3
9 I 3
10 J 3
好了,记住这个写法就行了。下面我们扩展一下。直接给n()
函数,他统计的是分组的频次,如果我想计算的是分组后,每个小组内部的信息怎么办,比如求第一列的最大值就可以这样做。
data %>%
group_by(ID) %>%
summarise(sample1=max(sample1))
# A tibble: 26 x 2
ID sample1
<fct> <int>
1 A 990
2 B 759
3 C 752
4 D 872
5 E 672
6 F 905
7 G 649
8 H 918
9 I 579
10 J 611
还可以用summarise_at
函数这样做,对比一下差异。
data %>%
group_by(ID) %>%
summarise_at("sample1",max)
那么summarise
中除了,n()
和max()
函数,还能放哪些呢。
简单的说,只要是能够对向量起作用的函数,都可以放在里面,比如。
mean(): the mean AKA the average
sd(): the standard deviation, which is a measure of spread
min() and max(): the minimum and maximum values respectively
IQR(): Interquartile range
sum(): the sum
n(): a count of the number of rows/observations in each group
这段话是来自于一个网上教程,叫,R数据处理。
https://cengel.github.io/R-data-wrangling/
现在我们要拓展一下了summarise
可以作用于多个列,比如
data %>%
group_by(ID) %>%
summarise(sample1=max(sample1),
sample2=max(sample2))
# A tibble: 26 x 3
ID sample1 sample2
<fct> <int> <int>
1 A 990 84
2 B 759 89
3 C 752 95
4 D 872 93
5 E 672 79
6 F 905 91
7 G 649 78
8 H 918 48
9 I 579 80
10 J 611 94
也可以用summarise_at
函数这样做,对比一下差异。
data %>%
group_by(ID) %>%
summarise_at(c("sample1","sample2"),max)
再拓展一下,内部的函数可以不一样,一个求最大值,一个求最小值
data %>%
group_by(ID) %>%
summarise(sample1=max(sample1),
sample2=min(sample2))
# A tibble: 26 x 3
ID sample1 sample2
<fct> <int> <int>
1 A 990 33
2 B 759 26
3 C 752 19
4 D 872 54
5 E 672 30
6 F 905 37
7 G 649 10
8 H 918 12
9 I 579 66
10 J 611 17
只要你有闲心,你甚至可以把每一列都操作一下
data %>%
group_by(ID) %>%
summarise(sample1=max(sample1),
sample2=max(sample2),
sample3=max(sample3))
用summarise_at
函数也是可以的。
data %>%
group_by(ID) %>%
summarise_at(c("sample1","sample2","sample3"),max)
假如像上面一样,每一个函数都是一样的,那么就可以用summarise_all
因为这个是对全部列起作用,所以函数内部可以不用写参数。
data %>%
group_by(ID) %>%
summarise_all(max)
# A tibble: 26 x 4
ID sample1 sample2 sample3
<fct> <int> <int> <int>
1 A 990 84 443
2 B 759 89 181
3 C 752 95 413
4 D 872 93 287
5 E 672 79 471
6 F 905 91 371
7 G 649 78 491
8 H 918 48 476
9 I 579 80 484
10 J 611 94 392
刚才是求最大值,现在尝试求平均值试试
data %>%
group_by(ID) %>%
summarise_all(mean)
# A tibble: 26 x 4
ID sample1 sample2 sample3
<fct> <dbl> <dbl> <dbl>
1 A 663. 53.7 261.
2 B 521 54.7 124.
3 C 476. 47.3 334
4 D 442. 74.3 257.
5 E 554 49.7 411
6 F 671. 56.3 222.
7 G 345. 50.3 397.
8 H 638. 35.3 259.
9 I 474. 72.3 316
10 J 323. 61.3 298
这一招用在甲基化位点和基因的对应关系那里很有用,比如,多个甲基化位点对应一个基因,我们可以用这里的方法选取最大值,最小值,或者平均值。
当然,我们想要一次性施加多个函数,也是可以的,这样写就行
data %>%
group_by(ID) %>%
summarise_all(list(max,min,mean))
# A tibble: 26 x 10
ID sample1_fn1 sample2_fn1 sample3_fn1 sample1_fn2 sample2_fn2 sample3_fn2 sample1_fn3 sample2_fn3 sample3_fn3
<fct> <int> <int> <int> <int> <int> <int> <dbl> <dbl> <dbl>
1 A 990 84 443 405 33 53 663. 53.7 261.
2 B 759 89 181 130 26 94 521 54.7 124.
3 C 752 95 413 47 19 233 476. 47.3 334
4 D 872 93 287 57 54 232 442. 74.3 257.
5 E 672 79 471 346 30 326 554 49.7 411
6 F 905 91 371 268 37 69 671. 56.3 222.
7 G 649 78 491 89 10 278 345. 50.3 397.
8 H 918 48 476 206 12 25 638. 35.3 259.
9 I 579 80 484 349 66 71 474. 72.3 316
10 J 611 94 392 49 17 237 323. 61.3 298
计算的结果,按照函数出现的顺序,依次排列。不过,看得有点混乱,我们可以通过赋值变量来改善一下
data %>%
group_by(ID) %>%
summarise_all(list(max = max,min = min,mean = mean))
这样通过列名就可以看得很清楚
# A tibble: 26 x 10
ID sample1_max sample2_max sample3_max sample1_min sample2_min sample3_min sample1_mean sample2_mean sample3_mean
<fct> <int> <int> <int> <int> <int> <int> <dbl> <dbl> <dbl>
1 A 990 84 443 405 33 53 663. 53.7 261.
2 B 759 89 181 130 26 94 521 54.7 124.
3 C 752 95 413 47 19 233 476. 47.3 334
4 D 872 93 287 57 54 232 442. 74.3 257.
5 E 672 79 471 346 30 326 554 49.7 411
6 F 905 91 371 268 37 69 671. 56.3 222.
7 G 649 78 491 89 10 278 345. 50.3 397.
8 H 918 48 476 206 12 25 638. 35.3 259.
9 I 579 80 484 349 66 71 474. 72.3 316
10 J 611 94 392 49 17 237 323. 61.3 298
这样,我们就介绍完了summarise
,summarise_at
,summarise_all
,而且也知道了内部使用的函数有哪些。
但是还有一个问题,如果数据比较多,但是有一些列不能被施加函数,怎么办呢。土方法就是,用summarise
或者summarise_at
一一指定,但是数据多的话太麻烦了,有没有什么好方法呢,有。
我们重新创建一个测试数据
data <- data.frame(ID=rep(LETTERS,each=3),
sample1=sample(seq(10,1000),78),
sample2=sample(seq(10,100),78),
sample3=sample(letters,78,replace = T))
这个数据的有一列不是数字,是字母,如果我想分组对所有列求和怎么办?通常的写法是这样的
data %>%
group_by(ID) %>%
summarise_all(max)
会报错的
Error in Summary.factor(c(4L, 5L, 2L), na.rm = FALSE) :
‘max’ not meaningful for factors
此时我们可以用另外一个函数summarise_if
来判断,是数值的计算,不是数值的就不要
data %>%
group_by(ID) %>%
summarise_if(is.numeric,max)
# A tibble: 26 x 3
ID sample1 sample2
<fct> <int> <int>
1 A 681 89
2 B 831 61
3 C 616 97
4 D 915 29
5 E 807 55
6 F 500 98
7 G 822 67
8 H 804 94
9 I 871 100
10 J 876 83
这样group_by
联合summarise
的用法就讲完了,实战运用请参考文章开头的几个帖子。
我们后面要讲一讲,gather
和spread
,以及他们是如何遭遗弃的故事。